#include <iostream>
#include <mutex>
#include <atomic>

using namespace std;

class Singleton {
public:
    static Singleton* getInstance() {
        Singleton* instance = instance_.load(std::memory_order_relaxed);
        if (!instance) {
            std::lock_guard<std::mutex> lock(mutex_);
            instance = instance_.load(std::memory_order_relaxed);
            if (!instance) {
                instance = new Singleton();
                instance_.store(instance, std::memory_order_release);
            }
        }
        return instance;
    }

    // 禁止拷贝构造和赋值
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    Singleton() {
        std::cout << "Singleton created" << std::endl;
    }
    ~Singleton() {
        std::cout << "Singleton destroyed" << std::endl;
    }

    static std::atomic<Singleton*> instance_;
    static std::mutex mutex_;
};

std::atomic<Singleton*> Singleton::instance_{nullptr};
std::mutex Singleton::mutex_;

// 对互斥锁操作的封装
class CMutex
{
public:
	CMutex(){pthread_mutex_init(&mutex, NULL);}  // 初始化锁
	~CMutex(){pthread_mutex_destroy(&mutex);}  // 销毁锁 
	void lock(){pthread_mutex_lock(&mutex);}  // 获取锁
	void unlock(){pthread_mutex_unlock(&mutex);}  // 释放锁
private:
	pthread_mutex_t mutex;
};

class CSingleton
{
public:
    static CSingleton* getInstance()
    {
        if (nullptr == single)
        {
			// 获取互斥锁
			mutex.lock();
			/* 
			这里需要再添加一个if判断，否则当两个
			线程都进入这里，又会多次new对象，不符合
			单例模式的涉及
			*/
			if(nullptr == single)
			{
				single = new CSingleton();
			}
			// 释放互斥锁
			mutex.unlock();
        }
        return single;
    }
private:
    static CSingleton *single;
    CSingleton() { cout << "CSingleton()" << endl; }
    ~CSingleton() { cout << "~CSingleton()" << endl; }
    CSingleton(const CSingleton&);

    // 定义一个嵌套类，在该类的析构函数中，自动释放外层类的资源
    class CRelease
    {
    public:
        ~CRelease() { delete single; }
    };
    // 通过该静态对象在程序结束时自动析构的特点，来释放外层类的对象资源
    static CRelease release;
    //线程间的静态互斥锁
	static CMutex mutex;
};
CSingleton* CSingleton::single = nullptr;
CSingleton::CRelease CSingleton::release;

// 懒汉式单例模式，顾名思义，就是对象的实例化，延迟到第一次使用它的时候。
int main() {
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();

    CSingleton *p1 = CSingleton::getInstance();
    CSingleton *p2 = CSingleton::getInstance();
    CSingleton *p3 = CSingleton::getInstance();
    cout << p1 << " " << p2 << " " << p3 << endl;
    return 0;
}